using UniversalAdmin.Application.Dtos.Log;
using UniversalAdmin.Application.Services.Interfaces;
using UniversalAdmin.Domain.Entities.App;
using UniversalAdmin.Infrastructure.Data.Contexts;
using Microsoft.EntityFrameworkCore;
using System.Text;
using Microsoft.Extensions.DependencyInjection;

public class LogService : ILogService
{
    private readonly IServiceScopeFactory _scopeFactory;
    public LogService(IServiceScopeFactory scopeFactory)
    {
        _scopeFactory = scopeFactory;
    }

    public async Task AddAsync(CreateLogDto dto)
    {
        using var scope = _scopeFactory.CreateScope();
        var db = scope.ServiceProvider.GetRequiredService<AdminDbContext>();
        try
        {
            var log = new OperationLog
            {
                UserId = dto.UserId,
                Action = dto.Action,
                Resource = dto.Resource,
                ResourceId = dto.ResourceId,
                IpAddress = dto.IpAddress,
                UserAgent = dto.UserAgent,
                // CreatedAt 由基础实体自动赋值
            };
            db.OperationLogs.Add(log);
            await db.SaveChangesAsync();
            Console.WriteLine("日志已写入数据库");
        }
        catch (Exception ex)
        {
            Console.WriteLine("写入日志失败：" + ex.Message);
            throw;
        }
    }

    public async Task<(int TotalCount, List<LogDto> Items)> QueryAsync(LogQueryDto dto)
    {
        using var scope = _scopeFactory.CreateScope();
        var db = scope.ServiceProvider.GetRequiredService<AdminDbContext>();
        var query = db.OperationLogs.AsQueryable();
        
        if (dto.StartTime.HasValue)
            query = query.Where(x => x.CreatedAt >= dto.StartTime.Value);
        if (dto.EndTime.HasValue)
            query = query.Where(x => x.CreatedAt <= dto.EndTime.Value);
        
        // 如果指定了用户名称查询，先获取匹配的用户ID
        if (!string.IsNullOrEmpty(dto.UserName))
        {
            var matchingUserIds = await db.Users
                .Where(u => u.Username.Contains(dto.UserName))
                .Select(u => u.Id)
                .ToListAsync();
            
            if (matchingUserIds.Any())
            {
                query = query.Where(x => x.UserId.HasValue && matchingUserIds.Contains(x.UserId.Value));
            }
            else
            {
                // 如果没有找到匹配的用户，返回空结果
                return (0, new List<LogDto>());
            }
        }
        else if (dto.UserId.HasValue)
        {
            // 保留原有的按用户ID查询功能作为备用
            query = query.Where(x => x.UserId == dto.UserId);
        }
        
        // 修复操作类型筛选：只有当Action不是"全部"时才进行过滤
        if (!string.IsNullOrEmpty(dto.Action) && dto.Action.ToLower() != "全部")
            query = query.Where(x => x.Action == dto.Action);

        var total = await query.CountAsync();
        var items = await query
            .OrderByDescending(x => x.CreatedAt)
            .Skip((dto.PageIndex - 1) * dto.PageSize)
            .Take(dto.PageSize)
            .ToListAsync();

        // 获取所有相关的用户ID
        var userIds = items.Where(x => x.UserId.HasValue).Select(x => x.UserId.Value).Distinct().ToList();
        var users = userIds.Any() ? await db.Users.Where(u => userIds.Contains(u.Id)).ToDictionaryAsync(u => u.Id, u => u.Username) : new Dictionary<Guid, string>();

        // 获取所有相关的资源ID（用户ID）
        var resourceUserIds = items.Where(x => x.ResourceId.HasValue).Select(x => x.ResourceId.Value).Distinct().ToList();
        var resourceUsers = resourceUserIds.Any() ? await db.Users.Where(u => resourceUserIds.Contains(u.Id)).ToDictionaryAsync(u => u.Id, u => u.Username) : new Dictionary<Guid, string>();

        var result = new List<LogDto>();
        var serialNumber = (dto.PageIndex - 1) * dto.PageSize + 1;

        foreach (var item in items)
        {
            var userName = item.UserId.HasValue && users.ContainsKey(item.UserId.Value) ? users[item.UserId.Value] : null;
            var resourceUserName = item.ResourceId.HasValue && resourceUsers.ContainsKey(item.ResourceId.Value) ? resourceUsers[item.ResourceId.Value] : null;

            var formattedResource = FormatResource(item.Action, item.Resource, resourceUserName, item.ResourceId);

            result.Add(new LogDto
            {
                Id = item.Id,
                SerialNumber = serialNumber++,
                UserId = item.UserId,
                UserName = userName,
                Action = item.Action,
                Resource = item.Resource,
                ResourceId = item.ResourceId,
                FormattedResource = formattedResource,
                IpAddress = item.IpAddress,
                UserAgent = item.UserAgent,
                CreatedAt = item.CreatedAt
            });
        }

        return (total, result);
    }

    private string FormatResource(string? action, string? resource, string? resourceUserName, Guid? resourceId)
    {
        if (string.IsNullOrEmpty(action))
            return resource ?? string.Empty;

        switch (action.ToLower())
        {
            case "usercreated":
            case "create":
                return $"创建了用户 {resourceUserName ?? resourceId?.ToString() ?? "未知"}";
            case "update":
                return $"更新了用户 {resourceUserName ?? resourceId?.ToString() ?? "未知"} 的信息";
            case "userdeleted":
            case "delete":
                return $"删除了用户 {resourceUserName ?? resourceId?.ToString() ?? "未知"}";
            case "query":
                return $"查询了用户 {resourceUserName ?? resourceId?.ToString() ?? "未知"} 的详细信息";
            case "querylist":
                return "查询了用户列表";
            case "querybyusername":
                return "按用户名查询了用户";
            case "querybyusernamefuzzy":
                return "模糊查询了用户";
            case "queryuserroles":
                return $"查询了用户 {resourceUserName ?? resourceId?.ToString() ?? "未知"} 的角色信息";
            case "assignrole":
                return $"为用户 {resourceUserName ?? resourceId?.ToString() ?? "未知"} 分配了角色";
            case "removerole":
                return $"移除了用户 {resourceUserName ?? resourceId?.ToString() ?? "未知"} 的角色";
            case "enable":
                return $"启用了用户 {resourceUserName ?? resourceId?.ToString() ?? "未知"}";
            case "disable":
                return $"禁用了用户 {resourceUserName ?? resourceId?.ToString() ?? "未知"}";
            case "login":
                return "用户登录了系统";
            case "logout":
                return "用户退出了系统";
            case "changepassword":
                return $"修改了用户 {resourceUserName ?? resourceId?.ToString() ?? "未知"} 的密码";
            case "resetpassword":
                return $"重置了用户 {resourceUserName ?? resourceId?.ToString() ?? "未知"} 的密码";
            case "lock":
                return $"锁定了用户 {resourceUserName ?? resourceId?.ToString() ?? "未知"}";
            case "unlock":
                return $"解锁了用户 {resourceUserName ?? resourceId?.ToString() ?? "未知"}";
            case "export":
                return "导出了用户数据";
            case "import":
                return "导入了用户数据";
            case "batchdelete":
                return "批量删除了用户";
            case "batchupdate":
                return "批量更新了用户信息";
            case "batchassignrole":
                return "批量分配了用户角色";
            case "audit":
                return $"审核了用户 {resourceUserName ?? resourceId?.ToString() ?? "未知"}";
            case "approve":
                return $"批准了用户 {resourceUserName ?? resourceId?.ToString() ?? "未知"} 的申请";
            case "reject":
                return $"拒绝了用户 {resourceUserName ?? resourceId?.ToString() ?? "未知"} 的申请";
            default:
                return resource ?? string.Empty;
        }
    }

    public async Task<byte[]> ExportAsync(LogQueryDto dto)
    {
        using var scope = _scopeFactory.CreateScope();
        var db = scope.ServiceProvider.GetRequiredService<AdminDbContext>();
        var query = db.OperationLogs.AsQueryable();
        
        if (dto.StartTime.HasValue)
            query = query.Where(x => x.CreatedAt >= dto.StartTime.Value);
        if (dto.EndTime.HasValue)
            query = query.Where(x => x.CreatedAt <= dto.EndTime.Value);
        
        // 如果指定了用户名称查询，先获取匹配的用户ID
        if (!string.IsNullOrEmpty(dto.UserName))
        {
            var matchingUserIds = await db.Users
                .Where(u => u.Username.Contains(dto.UserName))
                .Select(u => u.Id)
                .ToListAsync();
            
            if (matchingUserIds.Any())
            {
                query = query.Where(x => x.UserId.HasValue && matchingUserIds.Contains(x.UserId.Value));
            }
            else
            {
                // 如果没有找到匹配的用户，返回空结果
                return Encoding.UTF8.GetBytes("序号,用户ID,用户名,操作类型,操作内容,资源ID,操作时间,IP地址,UserAgent\n");
            }
        }
        else if (dto.UserId.HasValue)
        {
            // 保留原有的按用户ID查询功能作为备用
            query = query.Where(x => x.UserId == dto.UserId);
        }
        
        // 修复操作类型筛选：只有当Action不是"全部"时才进行过滤
        if (!string.IsNullOrEmpty(dto.Action) && dto.Action.ToLower() != "全部")
            query = query.Where(x => x.Action == dto.Action);

        var items = await query.OrderByDescending(x => x.CreatedAt).ToListAsync();
        
        // 获取所有相关的用户ID
        var userIds = items.Where(x => x.UserId.HasValue).Select(x => x.UserId.Value).Distinct().ToList();
        var users = userIds.Any() ? await db.Users.Where(u => userIds.Contains(u.Id)).ToDictionaryAsync(u => u.Id, u => u.Username) : new Dictionary<Guid, string>();

        // 获取所有相关的资源ID（用户ID）
        var resourceUserIds = items.Where(x => x.ResourceId.HasValue).Select(x => x.ResourceId.Value).Distinct().ToList();
        var resourceUsers = resourceUserIds.Any() ? await db.Users.Where(u => resourceUserIds.Contains(u.Id)).ToDictionaryAsync(u => u.Id, u => u.Username) : new Dictionary<Guid, string>();

        var sb = new StringBuilder();
        sb.AppendLine("序号,用户ID,用户名,操作类型,操作内容,资源ID,操作时间,IP地址,UserAgent");
        
        var serialNumber = 1;
        foreach (var log in items)
        {
            var userName = log.UserId.HasValue && users.ContainsKey(log.UserId.Value) ? users[log.UserId.Value] : "";
            var resourceUserName = log.ResourceId.HasValue && resourceUsers.ContainsKey(log.ResourceId.Value) ? resourceUsers[log.ResourceId.Value] : "";
            var formattedResource = FormatResource(log.Action, log.Resource, resourceUserName, log.ResourceId);
            
            sb.AppendLine($"{serialNumber++},{log.UserId},{userName},{log.Action},{formattedResource},{log.ResourceId},{log.CreatedAt},{log.IpAddress},{log.UserAgent}");
        }
        
        return Encoding.UTF8.GetBytes(sb.ToString());
    }

     public async Task CreateLogAsync(CreateLogDto logDto, CancellationToken cancellationToken)
        {
            using var scope = _scopeFactory.CreateScope();
            var db = scope.ServiceProvider.GetRequiredService<AdminDbContext>();
            var logEntry = new OperationLog
            {
                UserId = logDto.UserId,
                Action = logDto.Action,
                Resource = logDto.Resource
            };

            db.OperationLogs.Add(logEntry);
            await db.SaveChangesAsync(cancellationToken);
        }
} 